import java.net.*;
import java.io.*;
import java.math.*;

public class PlayerServerServant extends Thread{

    Socket connection;
    Player p;

    public PlayerServerServant(Socket connection, Player p){
        this.connection = connection;
        this.p = p;
    }

    public void run(){        
        Utilities.lock.lock();
        try{
            ObjectInputStream in = new ObjectInputStream(connection.getInputStream());
            int code = (Integer)in.readObject();
            int sender = (Integer)in.readObject();
            BigInteger share1, share2;
            int caller;
            switch(code){            
            case Utilities.doubleShareRandom:
                share1 = (BigInteger)in.readObject();
                share2 = (BigInteger)in.readObject();
                p.receiveDoubleShare(share1, share2, sender, null);
                break;
            
            case Utilities.receiveCheckDoubleShare:
                share1 = (BigInteger)in.readObject();
                share2 = (BigInteger)in.readObject();
                p.receiveCheckDoubleShare(share1, share2, sender);
                break;
            
            case Utilities.DOUBLESHARE_WAITFORCHECK:
                p.doubleShare_waitForCheck(sender);
                break;

            case Utilities.reconsPubl:
                share1 = (BigInteger)in.readObject();
                int degree = (Integer)in.readObject();
                caller = (Integer)in.readObject();
                p.receiveReconsPubl(share1, degree, sender, caller, null);
                break;
            
            case Utilities.returnReconsPubl:
                share1 = (BigInteger)in.readObject();
                degree = (Integer)in.readObject();
                caller = (Integer)in.readObject();
                p.reconsPublContinue(share1, degree, sender, caller);
                break;

            case Utilities.FAULTDETECTION:
                boolean happy = (Boolean)in.readObject();
                p.faultDetectionReceive(happy, sender);
                break;

            case Utilities.FAULTDETECTION_PART2:
                boolean happy2 = (Boolean)in.readObject();
                p.faultDetectionPart2(happy2, sender);
                break;

            case Utilities.FAULTLOCALIZATION:
                MessageList msgs = (MessageList)in.readObject();
                p.faultLocalizationReceive(msgs, sender);
                break;

            case Utilities.ACCUSATION:
                int p1 = (Integer)in.readObject();
                int p2 = (Integer)in.readObject();
                Object x = in.readObject();
                Object x_prime = in.readObject();
                int index = (Integer)in.readObject();
                p.accusation(p1, p2, x, x_prime, index); 
                break;

            case Utilities.ACCUSATIONRESPONSE:
                boolean response = (Boolean)in.readObject();
                p.accusationResponse(response, sender);
                break;

            default:
                //Something is wrong. Ignoring input
                //must try again
                System.err.println("Something went wrong.. "+
                                   "Code not recognized by server - ignoring input");         
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
        catch(ClassNotFoundException e){
            System.out.println("received input that was not understood. ");
        }
        finally{            
            if(Utilities.lock.getHoldCount() > 0)
                Utilities.lock.unlock();
            interrupt();
        }
    }
}